﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ReadWriteCsv;
using System.Text.RegularExpressions;

namespace StockAnomalyDetector
{

    public enum Signal
    {
        up,
        down,
        none
    }
    public class FormerData
    {
        public double endPrice;
        public double limitPrice;
        public string code;
        public Signal signal;

        public FormerData(double endPrice, string code, Signal signal, double limitPrice)
        {
            this.endPrice = endPrice;
            this.code = code;
            this.signal = signal; // up则昨天出现涨停
            this.limitPrice = limitPrice;
        }
    }
    class InLimitUpDown
    {
        public Queue<FormerData> formerData = new Queue<FormerData>(3000);
        public Queue<FormerData> currentData = new Queue<FormerData>(3000); 
        public static List<string> exceptionList = new List<string>() { "stockcode,firstDate,secondDate,upOrDown,firstLimit,secondLimit" };//暂时存储所有Csv文件里的Repetition异常
        public static CsvFileWriter writer = new CsvFileWriter(@"D:\股票数据\" + "inlimitupdown" + ".csv");

        public void Reset()
        {
            formerData = currentData;
            currentData = new Queue<FormerData>(3000);
        }
    }
    class LimitUpDown
    {
        protected int time;
        protected double price;
        protected char BorS;
        protected int quantity;
        protected CsvRow csvRow;
        FormerData former;
        bool doCompare;

        public LimitUpDown(CsvRow r, FormerData f, bool d)
        {
            csvRow = r;
            former = f;
            doCompare = d;
        }

        //每个异常类的Analyze函数实现需要在函数体一开始调用该函数 以简化row[i]的转化
        public void ParseRow()
        {
            time = Convert.ToInt32(csvRow[0]);
            price = Convert.ToDouble(csvRow[1]);
            BorS = Convert.ToChar(csvRow[2]);
            quantity = Convert.ToInt32(csvRow[3]);
        }
        
        private bool todayUp; // 当天有涨停
        private bool todayDown;

        private double total;
        private int count;
        private double avg;

        private double limit;

        private double paramUp = 1.099;
        private double paramDown = 0.901;

        public void Analyze()
        {
            ParseRow();

            // 找出收盘价
            if (time >= 145900)
            {
                total += price*quantity;
                count += quantity;
                avg = total / count;
            }

            if (!doCompare)
            {
                return;
            }

            if (price >= former.endPrice * paramUp)
            {
                todayUp = true;
                limit = price;
            }
            else if (price <= former.endPrice*paramDown && price > former.endPrice*0.880)
            {
                todayDown = true;
                limit = price;
            }

            
        }

        public void End(string sourceName, Queue<FormerData> queue, string formerDate)
        {
            // 记录异常，并且今天的数据入列
            var stockcode = Convert.ToString(Regex.Match(sourceName, @"[A-Z]{2}\d{6}"));
            var firstdate= Convert.ToString(Regex.Match(formerDate, @"\d{8}"));
            var date = Convert.ToString(Regex.Match(sourceName, @"\d{8}"));

            if (todayUp)
            {
                queue.Enqueue(new FormerData(avg, stockcode, Signal.up, limit));
            }
            else if (todayDown)
            {
                queue.Enqueue(new FormerData(avg, stockcode, Signal.down, limit));
            }
            else
            {
                queue.Enqueue(new FormerData(avg, stockcode, Signal.none, 0));
            }

            if (!doCompare)
            {
                return;
            }

            // 判断今天有无异常
            if (former.signal == Signal.none)
            {
                return;
            }
            else if (todayUp && former.signal == Signal.down)
            {
                Console.WriteLine("InterDayLimitUpDown: {0},{1},{2},{3},{4},{5}", stockcode, firstdate, date, "up", former.limitPrice, limit);
                InLimitUpDown.exceptionList.Add(string.Format("{0},{1},{2},{3},{4},{5}", stockcode, firstdate, date, "up", former.limitPrice, limit));
            }
            else if (todayDown && former.signal == Signal.up)
            {
                Console.WriteLine("InterDayLimitUpDown: {0},{1},{2},{3},{4},{5}", stockcode, firstdate, date, "down", former.limitPrice, limit);
                InLimitUpDown.exceptionList.Add(string.Format("{0},{1},{2},{3},{4},{5}", stockcode, firstdate, date, "down", former.limitPrice, limit));
            }
        }


    }
}
